package ws.db.writetable;

import ws.db.*;
import ws.db.execsql.ExecSQL;
import ws.log.*;
import ws.db.sql.InsertSQLUseArray;
import ws.db.sql.SQLInterface;
import ws.db.sql.UpdateSQLUseArray;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * @param:
 * 		m_table - the table would be insert.
 * 		obj - the object you want to save.
 * 		columnAttrPairs - the column and attribution pairs.
 * @return:
 * 		boolean - if insert success return true,else return false.
 * */

abstract public class WriteObject {

	 protected String table;
	 protected String where;
	 protected Object obj;		//use for one obj operate.
	
	 
	 protected ArrayList<ColumnAttrPair> columnAttrPairs;
	 
	/**
	 * Get the attribution`s value using reflectiong method.
	 * @param:
	 * 		obj - the object which will be save.
	 * 		columnAttrPairs - the column and attribution pair.
	 * @return:
	 * 		String[] - the values of attributions.
	 * @exception:
	 * 		throw NullPointerException when the attribution is null.
	 * 
	 * */
	protected String[] getValues(Object obj,
					ArrayList<ColumnAttrPair> columnAttrPairs) 
					throws NullPointerException{
		
		String[] values = new String[columnAttrPairs.size()];
		Class objclass = obj.getClass();   
	    Iterator its = columnAttrPairs.iterator();
	    try{
	    	int i=0;
		    while(its.hasNext()){
		    	ColumnAttrPair eachpair = (ColumnAttrPair)its.next();
		    	System.out.println("attr="+eachpair.attr);
		    	Method method = objclass.getMethod("get"+eachpair.attr, null);      
				Object objvalue = method.invoke(obj, null);  
				
				String strvalue = getValue(objvalue);
				if(strvalue != null){
					values[i++] = strvalue;
				}else{
					throw new NullPointerException("Get "+eachpair.attr+" is null");
				}
				
		    }
	    }catch(NoSuchMethodException noSuchMethodEx){
	    	DoExceptionWork("没有对象方法 WriteObject.getValues",noSuchMethodEx,values);
	    }catch(InvocationTargetException invocationTargetEx){
	    	DoExceptionWork("Invocation WriteObject.getValues",invocationTargetEx,values);
		}catch(IllegalAccessException illegalAccessEx){
			DoExceptionWork("非法访问 WriteObject.getValues",illegalAccessEx,values);
		}
		return values;
	
	}
	
	private void DoExceptionWork(String msg,Exception ex,Object obj){
		Log.writeDBMiddleLayerLog(msg, ex);
		obj = null;
	}
	
	/**
	 *Change Object to special Type.
	 *If object is Date type then use the special format to change.
	 * */
	private String getValue(Object obj){
		
		if(obj==null){
			return null;
		}
		
		Class objclass = obj.getClass();
		System.out.println("objclass="+objclass);
		String value = null;
		if(objclass.isAssignableFrom(Date.class)){
			SimpleDateFormat dateformat1=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			value =dateformat1.format(obj);
		}
		else if(objclass.isAssignableFrom(Boolean.class)){//判断是否传入boolean类型进入
			System.out.println("obj="+obj);
			if(((Boolean)obj).booleanValue()){
				value = "1";
			}else{
				value = "0";
			}
		}
		else{
			value = new String(obj.toString());
		}
		
		System.out.println("value="+value);
		return  value;
		
	}

	
	/**
	 * The function provide operat one record.
	 * I think this function should return int type.
	 * Because it can`t decide true or false by result equal 1 or not .
	 * */
	public int  operatOneRecord(){
		int result = 0;
		String values[] = null;
		try{
			values = this.getValues(obj, columnAttrPairs);
		}catch(NullPointerException nullPointerEx){
			Log.writeDBMiddleLayerLog("从类对象得到值错误", nullPointerEx);
		}
		if( null != values ){
			String columns[] = new String[values.length];
			ColumnAttrPair.ChangArrayListToStringArray(columnAttrPairs, columns);
			SQLInterface sql = constructSQL(table, where, columns, values);
			ExecSQL execsql = new ExecSQL();
			execsql.setDirectconn(true);
			result = execsql.execOneCommand(sql);
			
		}
		return result;
	}
	
	
	

	/**
	 * Insert ,Update use different SQL.
	 * So InsertObject and UpdateObject will overide this function.
	 * 
	 * */
	abstract protected SQLInterface constructSQL(String m_table,String m_where,String[] columns,String[] values);
}
